import cn.wxw.ai.model.entity.ChatEntity;
import cn.wxw.ai.common.UserContextHolder;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.*;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @description: 基于 Redis 的 ChatMemory
 * @author: wxw
 * @date: 2025/9/16
 */
@Slf4j
public class ChatRedisMemory implements ChatMemory {

    /**
     * 聊天记录的 Redis key 前缀
     */
    private static final String KEY_PREFIX = "chat:history:";

    /**
     *  取最后 maxMessages 条聊天记录
     */
    private final int maxMessages;

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * 用户唯一标识, 用来隔离不同用户的记忆
     */
    private final String defaultUID;

    public ChatRedisMemory(RedisTemplate<String, Object> redisTemplate,
                           int maxMessages,
                           String defaultUID) {
        this.redisTemplate = redisTemplate;
        this.maxMessages = maxMessages;
        this.defaultUID = defaultUID;
    }

    /**
     * 获取当前有效的用户ID
     */
    private String getCurrentUID() {
        String username = UserContextHolder.getUsername();
        return username != null ? username : defaultUID;
    }

    /**
     * 添加聊天记录
     * @param conversationId
     * @param messages
     */
    @Override
    public void add(String conversationId, List<Message> messages) {
        String key = KEY_PREFIX + getCurrentUID() + ":" + conversationId;
        List<ChatEntity> chatEntityList = new ArrayList<>();
        for (Message message : messages) {
            // 解析消息内容
            String text = message.getText();

            // 构造聊天记录实体
            ChatEntity chatEntity = new ChatEntity();
            chatEntity.setChatId(conversationId);
            chatEntity.setType(message.getMessageType().getValue());
            chatEntity.setContent(text);
            chatEntityList.add(chatEntity);
        }
        // 保存聊天记录到 Redis
        redisTemplate.opsForList().rightPushAll(key, chatEntityList.toArray());
        redisTemplate.expire(key, 30, TimeUnit.DAYS);
        log.info("聊天记录已保存");
    }

    /**
     * 获取聊天记录
     * @param conversationId
     * @return
     */
    @Override
    public List<Message> get(String conversationId) {
        // 使用pattern获取当前用户的所有会话key
        String pattern = KEY_PREFIX + getCurrentUID() + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        
        // 存储所有会话的聊天记录
        List<Message> allMessages = new ArrayList<>();
        
        if (keys != null && !keys.isEmpty()) {
            for (String key : keys) {
                Long size = redisTemplate.opsForList().size(key);
                if (size != null && size > 0) {
                    List<Object> objectList = redisTemplate.opsForList().range(key, 0, -1);
                    
                    // 解析聊天记录实体并添加到总列表
                    ObjectMapper mapper = new ObjectMapper();
                    for (Object object : objectList) {
                        try {
                            // 标准转换
                            ChatEntity chatEntity = mapper.convertValue(object, ChatEntity.class);
                            
                            // 解码内容
                            String decodedContent = decodeChineseContent(chatEntity.getContent());
                            chatEntity.setContent(decodedContent);
                            
                            Message message = null;
                            if (MessageType.USER.getValue().equals(chatEntity.getType())) {
                                message = new UserMessage(chatEntity.getContent());
                            } else if (MessageType.SYSTEM.getValue().equals(chatEntity.getType())) {
                                message = new SystemMessage(chatEntity.getContent());
                            } else if (MessageType.ASSISTANT.getValue().equals(chatEntity.getType())) {
                                message = new AssistantMessage(chatEntity.getContent());
                            }
                            
                            if (message != null) {
                                allMessages.add(message);
                            }
                        } catch (Exception e) {
                            log.error("解析聊天记录失败: {}", e.getMessage());
                        }
                    }
                }
            }
        }
        
        // 如果消息总数超过maxMessages，只返回最近的maxMessages条
        int totalMessages = allMessages.size();
        int startIndex = Math.max(0, totalMessages - maxMessages);
        
        log.info("聊天记录总条数: {}", totalMessages);
        log.info("返回的聊天记录条数: {}", Math.min(totalMessages, maxMessages));
        
        return allMessages.subList(startIndex, totalMessages);
    }

    /**
     * 解码内容
     * 处理 Redis 中存储的中文转义序列，同时保留英文内容
     */
    private String decodeChineseContent(String content) {
        if (content == null || content.isEmpty()) {
            return content;
        }
        
        try {
            // 检查是否包含十六进制编码的中文转义序列
            if (content.contains("\\x")) {
                StringBuilder sb = new StringBuilder();
                int i = 0;
                while (i < content.length()) {
                    // 寻找十六进制转义序列 \x 开始的位置
                    if (i + 3 < content.length() && content.charAt(i) == '\\' && content.charAt(i + 1) == 'x') {
                        try {
                            // 提取十六进制值
                            String hex = content.substring(i + 2, i + 4);
                            // 将十六进制转换为字符并添加到结果中
                            sb.append((char) Integer.parseInt(hex, 16));
                            // 跳过已处理的四个字符（\xHH）
                            i += 4;
                        } catch (NumberFormatException e) {
                            // 如果不是有效的十六进制值，保留原始字符
                            sb.append(content.charAt(i));
                            i++;
                        }
                    } else {
                        // 对于非转义序列的字符，直接保留
                        sb.append(content.charAt(i));
                        i++;
                    }
                }
                return sb.toString();
            }
            
            // 如果不包含转义序列，直接返回原始内容
            return content;
        } catch (Exception e) {
            log.warn("解码内容失败，使用原始内容: {}", e.getMessage());
            return content;
        }
    }

    /**
     * 清空聊天记录
     * @param conversationId
     */
    @Override
    public void clear(String conversationId) {

        // 删除用户的所有聊天记录
        String pattern = KEY_PREFIX + getCurrentUID() + ":*";
        Set<String> keys = redisTemplate.keys(pattern);
        if (keys != null && !keys.isEmpty()) {
            redisTemplate.delete(keys);
            log.info("已删除用户{}的所有聊天记录，共{}条", getCurrentUID(), keys.size());
        }
    }

    public static ChatRedisMemory.Builder builder() {
        return new ChatRedisMemory.Builder();
    }

    public static final class Builder {
        private RedisTemplate<String, Object> redisTemplate;
        private int maxMessages = 10;
        private String defaultUID;

        private Builder() {
        }

        public ChatRedisMemory.Builder redisTemplate(RedisTemplate<String, Object> redisTemplate) {
            this.redisTemplate = redisTemplate;
            return this;
        }

        public ChatRedisMemory.Builder maxMessages(int maxMessages) {
            this.maxMessages = maxMessages;
            return this;
        }

        public ChatRedisMemory.Builder uID(String defaultUID) {
            this.defaultUID = defaultUID;
            return this;
        }

        public ChatRedisMemory build() {
            if (this.redisTemplate == null) {
                this.redisTemplate = new RedisTemplate<>();
            }

            return new ChatRedisMemory(this.redisTemplate, this.maxMessages, this.defaultUID);
        }
    }
}
